﻿using JE.MicroMVVM.Example.Common;
using JE.MicroMVVM.Example.Contracts;
using JE.MicroMVVM.Example.DataModels;
using JE.MicroMVVM.Example.Views;
using MicroMVVM;
using MicroMVVM.Helpers;
using MicroMVVM.Interfaces;
using MicroMVVM.Navigation;
using MicroMVVM.Services;
using MicroMVVM.Services.Interfaces;
using System;
using System.Collections.Generic;
using System.Windows.Input;
using Windows.ApplicationModel.DataTransfer;
using Windows.UI.Xaml.Controls;

namespace JE.MicroMVVM.Example.ViewModels
{
    [ExportViewModel("MainPageViewModel")]
    public class MainPageViewModel : BindableBase, INavigation, IDesigntimeAware, IShareableContent
    {
        private readonly IServiceOne _serviceOne;
        private readonly IServiceTwo _serviceTwo;
        private readonly IServiceThree _serviceThree;
        private readonly IConnectionService _connectionService;
        private readonly IVisualStateManager _visualStateManager;
        private readonly IToastMessageService _toastMessageService;
        private readonly IStorageFileService _storageFileService;
        private string _title;
        private string _title1;
        private string _title2;
        private string _title3;
        private string _status;
        private readonly DataModelOne _dataModelOne;
        private readonly DataModelTwo _dataModelTwo;
        private readonly DataModelThree _dataModelThree;

        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public string Title1
        {
            get { return _title1; }
            set { SetProperty(ref _title1, value); }
        }

        public string Title2
        {
            get { return _title2; }
            set { SetProperty(ref _title2, value); }
        }

        public string Title3
        {
            get { return _title3; }
            set { SetProperty(ref _title3, value); }
        }

        public string Status
        {
            get { return _status; }
            set { SetProperty(ref _status, value); }
        }

        public ICommand NavigateCommand { get; set; }

        public ICommand StateCommand { get; set; }

        public MainPageViewModel()
        {
        }

        [ImportingConstructor]
        public MainPageViewModel(IServiceOne serviceOne, IServiceTwo serviceTwo, IServiceThree serviceThree, IConnectionService connectionService, IVisualStateManager visualStateManager, IToastMessageService toastMessageService, IStorageFileService storageFileService)
        {
            _serviceOne = serviceOne;
            _serviceTwo = serviceTwo;
            _serviceThree = serviceThree;
            _connectionService = connectionService;
            _visualStateManager = visualStateManager;
            _toastMessageService = toastMessageService;
            _storageFileService = storageFileService;

            Title = "Binding works for MainPageViewModel";

            _dataModelOne = _serviceOne.GetModel();
            _dataModelTwo = _serviceTwo.GetModel();
            _dataModelThree = _serviceThree.GetModel();

            Title1 = _dataModelOne.Title;
            Title2 = _dataModelTwo.Title;
            Title3 = _dataModelThree.Title;

            _connectionService.Status.Subscribe(status => Status = status ? "Connected" : "Not Connected");

            NavigateCommand = new DelegateCommand(OnNavigateCommand);
            StateCommand = new DelegateCommand(OnStateCommand);

            TestStorageFileService();
        }

        private async void TestStorageFileService()
        {
            const string filename = "abc.dat";
            const string content = "abcdefghijkl";

            var encoding = new System.Text.UTF8Encoding();
            var bytes = encoding.GetBytes(content);

            var result = await _storageFileService.WriteAsync(filename, bytes);

            var value = await _storageFileService.ReadAsync(filename);

            result = await _storageFileService.WriteAsync(filename, bytes, StorageLocation.Local);

            value = await _storageFileService.ReadAsync(filename, StorageLocation.Local);

            result = await _storageFileService.WriteAsync(filename, bytes, StorageLocation.Temporary);

            value = await _storageFileService.ReadAsync(filename, StorageLocation.Temporary);

            var exists =
                await _storageFileService.FileExistsAsync(filename, StorageLocation.InstalledLocation, "Content");

            result = await _storageFileService.WriteAsync(filename, bytes, StorageLocation.InstalledLocation, "content");

            value = await _storageFileService.ReadAsync(filename, StorageLocation.InstalledLocation, "content");
        }

        private void OnStateCommand(object obj)
        {
            var state = (string.IsNullOrEmpty(_visualStateManager.State) || _visualStateManager.State == "Default")
                            ? "TestState"
                            : "Default";

            _visualStateManager.GoToVisualState(state);

            _toastMessageService.ShowToastImageAndText01("ms-appx:///Assets/Canon150x100.jpg", "Visual state changed", "Alternate text");
        }

        private void OnNavigateCommand(object obj)
        {
            this.Navigate(typeof (SecondPage), _dataModelOne);
        }

        public void DesigntimeAware()
        {
            Title = "MainPageViewModel in Designtime Initialisation";

            var dataModelOne = DesignDataModel<DataModelOne, DataModelOne>.Get();
            var dataModelTwo = DesignDataModel<DataModelTwo, DataModelTwo>.Get();
            var dataModelThree = DesignDataModel<DataModelThree, DataModelThree>.Get();

            var dataModelOneList = DesignDataModel<DataModelOne, IEnumerable<DataModelOne>>.Get();
            var dataModelTwoList = DesignDataModel<DataModelTwo, IEnumerable<DataModelTwo>>.Get();
            var dataModelThreeList = DesignDataModel<DataModelThree, IEnumerable<DataModelThree>>.Get();

            Title1 = dataModelOne.Title;
            Title2 = dataModelTwo.Title;
            Title3 = dataModelThree.Title;
        }

        /// <summary>
        /// Gets/Sets the current page for this viewmodel.
        /// </summary>
        public Frame Current { get; set; }

        /// <summary>
        /// On navigating away from the current view.
        /// </summary>
        public void OnNavigating()
        {
            var test = string.Empty;
        }

        /// <summary>
        /// On finished navigating to the current view.
        /// </summary>
        /// <param name="parameter"></param>
        public void OnNavigated(object parameter)
        {
            var test = string.Empty;
        }

        public void SetShareableContent(DataTransferManager sender, DataRequestedEventArgs args)
        {
            var package = args.Request.Data;

            package.Properties.Title = "Title";

            package.SetHtmlFormat("This is the shareable content");
        }
    }
}